#include "StructDef.h"
#include "DrawTool.h"
#include "IrControl.h"
#include "Utility.h"
//#include "clr.h"
#include "Menu/MenuSystem.h"
//Bill modify
#include <errno.h>
#include "msgtool.h"
#include "PowerOff.h"
#include "TouchPanel.h"
#include <fcntl.h>//shining add

#define RECELEN	10
#define RECELON	8
#define RECEBUF RECELEN*RECELON
#define DEFUAL_OS_TIME 10000 //us

#define	ThreadInputStack	NULL 
#define	ThreadKeyStack		NULL 
#define	ThreadReadInfoStack		NULL 

//#define	UPGRADE_MAP_ALL
//#define	UPGRADE_CNS
//#define	UPGRADE_EXT2
//#define	UPGRADE_EXT2_UBOOT
#define	UPGRADE_CERTAIN_FILE




static TThreadFuncRtn FUNC_API	InputThread(TThreadFuncArg arg);
static TThreadFuncRtn FUNC_API	KeyThread(TThreadFuncArg arg);
static TThreadFuncRtn FUNC_API	ReadInfoThread(TThreadFuncArg arg);

#if	defined _WIN32
// NOTE: must be global in _WIN32/_SP8202 for main thread will exit immediately.
	TThread	ThreadInput;
	TThread	ThreadKey;
#endif


static	int os_sleep_time;	
extern unsigned char rece_handle;	
unsigned char dtpresent_flag;	

/*******************************************************************************/
//Bill modify

#define NavigationPath	"/mnt/mtd2/gtk_bf533.bin"
#define Engineer_cp "/bin/cp"
#ifdef UPGRADE_MAP_ALL
#define CMD_LIST 17
#elif defined UPGRADE_CNS
#define CMD_LIST 1
#elif defined UPGRADE_EXT2
#define CMD_LIST 13
#elif defined UPGRADE_EXT2_UBOOT
#define CMD_LIST 15
#endif



extern	unsigned char* _lcd_addr;	// lcd base address
extern	struct fb_var_screeninfo _fb_var_info;
extern	int  tsdev_fd;
extern  unsigned char send_data_buf[5];

int	NavigationInitFlag = 0;
pid_t	NavigationPID = -1;
pid_t	UIPID;

#ifdef UPGRADE_MAP_ALL
char* arg_lst[CMD_LIST] =
	{
	"umount /mnt/mtd1",
	"umount /mnt/mtd2",
	"umount /mnt/mtd3",
	"flash_eraseall /dev/mtd2",
	"flash_eraseall /dev/mtd3",
	"mount -t yaffs /dev/mtdblock2 /mnt/mtd2",
	"mount -t yaffs /dev/mtdblock3 /mnt/mtd3",
	"cp -rf /mnt/sd/GenieTek /mnt/mtd2/.",
	"cp -rf /mnt/sd/mtd3/data /mnt/mtd3/.",
	"cp -rf /mnt/sd/mtd3/res /mnt/mtd3/.",
	"cp -rf /mnt/sd/mtd3/system /mnt/mtd3/.",
	"cp -rf /mnt/sd/mtd3/cns.bin /mnt/mtd3/.",
	"cp -rf /mnt/sd/debug /mnt/mtd3/test0",
	"cp -rf /mnt/sd/debug /mnt/mtd3/test1",
	"cp -rf /mnt/sd/debug /mnt/mtd3/test2",
	"umount /mnt/mtd2",
	"umount /mnt/mtd3",
	};
#elif defined UPGRADE_CNS
	char* arg_lst[CMD_LIST] =
	{
	"cp -rf /mnt/sd/cns.bin /mnt/mtd3/.",
	};
	
#elif defined UPGRADE_EXT2
	char* arg_lst[CMD_LIST] =
	{
	"umount /mnt/mtd1",
	"umount /mnt/mtd2",
	"umount /mnt/mtd3",
	"rmmod bfin_nand",
	"insmod /mnt/sd/norflash/map_rom.ko",
	"insmod /mnt/sd/norflash/gen_probe.ko",
	"insmod /mnt/sd/norflash/cfi_util.ko",
	"insmod /mnt/sd/norflash/cfi_cmdset_0001.ko",
	"insmod /mnt/sd/norflash/cfi_cmdset_0002.ko",
	"insmod /mnt/sd/norflash/cfi_probe.ko",
	"insmod /mnt/sd/norflash/bf5xx-flash.cfi.ko",
	"flash_eraseall /dev/mtd2",
	"dd if=/mnt/sd/uImage.ext2 of=/dev/mtd2 bs=1k count=1920",
};
#elif defined UPGRADE_EXT2_UBOOT
	char* arg_lst[CMD_LIST] =
	{
	"umount /mnt/mtd1",
	"umount /mnt/mtd2",
	"umount /mnt/mtd3",	
	"rmmod bfin_nand",
	"insmod /mnt/sd/norflash/map_rom.ko",
	"insmod /mnt/sd/norflash/gen_probe.ko",
	"insmod /mnt/sd/norflash/cfi_util.ko",
	"insmod /mnt/sd/norflash/cfi_cmdset_0001.ko",
	"insmod /mnt/sd/norflash/cfi_cmdset_0002.ko",
	"insmod /mnt/sd/norflash/cfi_probe.ko",
	"insmod /mnt/sd/norflash/bf5xx-flash.cfi.ko",
	"flash_eraseall /dev/mtd1",
	"dd if=/mnt/sd/u-boot.bin of=/dev/mtd1 bs=1k count=128",
	"flash_eraseall /dev/mtd2",
	"dd if=/mnt/sd/uImage.ext2 of=/dev/mtd2 bs=1k count=1920",
};
#endif
	
	
int NavigationInit(void)
{
	int ret;
//	int test_flag = 1;
	Message qbuf;
	char teststr1[16];
	char teststr2[16];
	char* arg_list[4] =
	{
		"Bill test",
		NULL,
		NULL,
		NULL
	};
	
	sprintf(teststr1, "%d", (unsigned int)_lcd_addr);
	sprintf(teststr2, "%d", (unsigned int)(&_fb_var_info));
	arg_list[1] = teststr1;
	arg_list[2] = teststr2;
	
	UIPID = getpid();
	NavigationPID = vfork();

	if(NavigationPID >= 0) /* vfork succeeded */  
	{
		if (NavigationPID != 0)
		{
			printf("vofk_test2 PARENT: I am the parent process!\n");
			printf("vofk_test2 PARENT: Here's my PID: %d\n", getpid());
			printf("vofk_test2 PARENT: The value of my copy of childpid is %d\n", NavigationPID);
			printf("wait child process's initial finish message\n");
		}
		else
		{
			printf("vofk_test2 CHILD: I am the child process!\n");
			printf("vofk_test2 CHILD: Here's my PID: %d\n", getpid());
			printf("vofk_test2 CHILD: My parent's PID is: %d\n", getppid());
			ret = execv(NavigationPath, arg_list);
			printf("vofk_test2 execv(%s) failed!!  ret = %d, errno = %d\n", NavigationPath, ret, errno);
			return -1;
		}
	}
	else /* vfork returns -1 on failure */  
	{
		printf("vofk_test2 vfork failed!!!"); /* display error message */  
		return 0;
	}
	

}
#if	defined _BF533 || defined _DAVINCI
// NOTE: in PL1601 it need to put thread data in local stack and wait for the end of all threads
//       else the app will be unstable. 
	TThread	ThreadInput;
	TThread	ThreadKey;
	TThread	ThreadReadInfo;
#endif

int main()
{
		os_sleep_time = DEFUAL_OS_TIME;

	rece_handle = 0;
	dtpresent_flag = 1;
	if (fs_Initialize() == FALSE)
		return (0);
		
	LOG("fs_Initialize: ok\n");	
	if (dt_Initialize() == FALSE)
		return (0);
	LOG("dt_Initialize: ok\n");

	/*clr_init();
	LOG("clr_init: ok\n" );
	*/
	#ifdef CD_TEST_MODE
	dev_TouchPanelInit();
	
	if (InitBacklight())
		LOG("InitBacklight fail!\n" );
	
	LOG("UI system started!\n");	
	#if defined _HANGSHENG
	//dev_SPIInit();
	#endif
	
	#endif


	#ifdef MODULE_TEST_MODE
	dev_UartInit();
	#endif
	
	#ifdef ENGINEER_UPGRADE
	int i,ret=0;
	int fd_ext2=0,fd_uboot=0,fd_cns=0;
		#ifdef  UPGRADE_EXT2
		 fd_ext2 = open("/mnt/sd/uImage.ext2",O_RDONLY); 
		 printf ("open uImage.ext2: %d",fd_ext2);
     if (fd_ext2 == -1)
     {     	
     	TestMainInit(2);
     	sleep (2);
     	return (0);
    	}    	
		#elif defined(UPGRADE_EXT2_UBOOT)
		
		 fd_ext2 = open("/mnt/sd/u-boot.bin",O_RDONLY ); 
		 fd_uboot = open("/mnt/sd/uImage.ext2",O_RDONLY );     
     if ((fd_ext2 == -1)|| (fd_uboot == -1))
     {     	
     	TestMainInit(2);
     	sleep (2);
     	return (0);
    	}
    #elif defined (UPGRADE_CNS)
    	fd_cns = open("/mnt/sd/cns.bin",O_RDONLY );     
     if (fd_cns == -1)
     {     	
     	TestMainInit(2);
     	sleep (2);
     	return (0);
    	}
		#endif
		
	TestMainInit(1);
//////////////////// exec the command  //////////////////	
	#ifdef UPGRADE_CERTAIN_FILE
	system ("cp -rf /mnt/mtd3/gps_record0.TXT /mnt/sd/.");
	system ("cp -rf /mnt/mtd3/gps_record1.TXT /mnt/sd/.");
	system ("cp -rf /mnt/mtd3/gps_record2.TXT /mnt/sd/.");
	//system ("cp -rf /mnt/sd/mtd3/test0 /mnt/mtd3/.");
	//system ("cp -rf /mnt/sd/mtd3/test1 /mnt/mtd3/.");
	//system ("cp -rf /mnt/sd/mtd3/test2 /mnt/mtd3/.");
	#else
	for(i=0;i<CMD_LIST; i++)
	{
		system (arg_lst[i]);
	}
	#endif

	//ret = execl(Engineer_cp, "cp", "-rf",arg_sour_lst[0],arg_dest_lst[1], NULL);
	/*for(i=0;i<SOUR_LIST;i++)
	
	ret = execl(Engineer_cp, "cp", "-rf",arg_sour_lst[i],arg_dest_lst[j], NULL);
	//printf("execl(%s) ret = %d, errno = %d\n", Engineer_cp, ret, errno);
	//printf("it is here!\n");
	*/
	TestMainInit(0);
		sleep (2);
	printf("printf end!\n");
	#else
	TestMainInit();
	printf ("start  creat thread !\n");
	os_ThreadCreate(THREAD_PRIO_NORMAL, &ThreadInput, &InputThread, 0, STACK_SIZE_BIG*4, ThreadInputStack);
	os_ThreadCreate(THREAD_PRIO_NORMAL, &ThreadKey, &KeyThread, 0, STACK_SIZE_SMALL, ThreadKeyStack);
	os_ThreadCreate(THREAD_PRIO_NORMAL, &ThreadReadInfo,&ReadInfoThread, 0, STACK_SIZE_SMALL, ThreadReadInfoStack);

	os_ThreadResume(ThreadInput);
	os_ThreadResume(ThreadKey);
	os_ThreadResume(ThreadReadInfo);
	
	

	#if	defined _BF533 || defined _DAVINCI
	// Wait for the end of all threads
	os_ThreadJoin(ThreadInput);
	os_ThreadJoin(ThreadKey);
	os_ThreadJoin(ThreadReadInfo);
	#endif

	LOG("**  Exit main\n");
	
	#endif
	return (0);
}


/////////////////////////////////////////////////////////////////////////////
// All thread entries

TThreadFuncRtn FUNC_API InputThread(TThreadFuncArg arg)
{
	int key;
	int rc;

	LOG("**  Enter InputThread\n");

	while (1)
	{
	#ifdef CD_TEST_MODE
	key = dev_ReceiveBuf();
		if (key == IRC_READ_INFO)
				{
					ir_Input(key);				
				
				}
	#endif
		key = dev_KeyReadBuff();
		ir_Input(key);

		// just avoid switch menu incautiously while long loading time
		if( key == IRC_ENTER || key == IRC_RETURN )
			dev_KeyResetKeyBuff();
			
	/*	if ( ut_GetCardStatus() == FALSE )
			break;	// card been removed, no more (lock) user input!
			*/
	}


	LOG("**  Exit KeyThread\n");

	return 0;
}



TThreadFuncRtn FUNC_API KeyThread(TThreadFuncArg arg)
{
	int key;

	LOG("**  Enter KeyThread\n");

	if (dev_KeyInit())
	{
		while (1)
		{
			key = IRC_NO_KEY;

			if (key == IRC_NO_KEY)
			{
				// query touch device here
				// NOTE: this query can't be blocked
				key = dev_TouchPanelRead();
			}

/*			#if defined _WIN32 || !defined _PROJ_EL908	// EL908 has no keypad
			if (key == IRC_NO_KEY)
			{
				// query key device here
				// MEMO: this query can be blocked
				key = dev_KeyRead();
			}
			#endif
*/		
			if (key != IRC_NO_KEY)
			{
				dev_KeyAddToBuff( key );
			}

			os_Sleep(20);
		}
	}

	LOG("**  Exit KeyThread\n");

	return 0;
}

pthread_mutex_t dt_mutex;
pthread_cond_t dt_cond = PTHREAD_COND_INITIALIZER;

TThreadFuncRtn FUNC_API ReadInfoThread(TThreadFuncArg arg)
{
	int rc;
	
	pthread_mutex_init(&dt_mutex,NULL);
	
	pthread_cond_init(&dt_cond, NULL);	

	LOG("**  Enter ReadInfoThread\n");

	while (1)
	{
		pthread_cond_wait(&dt_cond,&dt_mutex);
		
//		pthread_mutex_lock(&dt_mutex);
		
		if (dtpresent_flag == 0){
			
//			pthread_mutex_unlock(&dt_mutex);	
			
			continue;
	  }	
	  		printf (" dtpresent_flag is %d \n",dtpresent_flag);
				dt_Present();
				dtpresent_flag = 0;
//				pthread_mutex_unlock(&dt_mutex);
			}

	
	LOG("**  ExitReadInfoThread\n");

#if	defined _BF533
	return 0;
#endif	
}
